﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp1.ViewModels;

using System.Net.Http;
using System.Net.Http.Headers;


using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Configuration;

using WpfApp1.Models;
using WpfApp1.Services;
using WpfApp1.Views;

using Newtonsoft.Json;

using System.Collections.ObjectModel;

using Gardener.Common;

using System.IO;

/// <summary>
/// 尝试订一个原则，在本地的所有操作都不对CRDC配置文件进行一个修改，只有在与服务器同步以后再进行与CRDC文件的交互，去主动更新配置文件,但是有一个例外，即当在本地修改文件名称时，需要在本地修改完文件名称后，对CRDC配置文件同步进行修改
/// 新增和修改文件夹时，必须通过服务器进行添加、删除、和修改，而对于文件的添加、删除和修改，可以在本地完成
/// 以上的原则作为文件操作的第一准则
/// 
/// 
/// </summary>
namespace WpfApp1
{
    public partial class MainWindow:Window
    {

        HttpClient httpClient = new HttpClient();

        /// <summary>
        /// 同步更新文件的参数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Commad_Handlepara(object sender, ExecutedRoutedEventArgs e)
        {
            //拿到文件夹ROOT的长度
            int temp = ConfigurationManager.AppSettings["RootPath"].Length;
            //文件名称
            string fileName = this.fileInfo.SelectedCells[0].Item.ToString().Substring(temp);
            fileName = PasswordGenerate.PathEncode(fileName);
            //拿到相关的用户配置信息
            string UserId = ConfigService.GetSettingString("UserId");
            string MajorID = ConfigService.GetSettingString("MajorID");
            //后期进行修改
            string datatype = "洞口";
            string description = "这个是一个测试的模型";
            string jsonstr = "22000";

            //构造网址路径
            string url = $"/api/file/json-data/{fileName}/{jsonstr}/{MajorID}/{datatype}/{description}";
            var respone = await httpClient.GetAsync(url);
            respone.EnsureSuccessStatusCode();
            var product = await respone.Content.ReadFromJsonAsync<ApiResult<string>>();
            string result = product.Data;
            if (result == "good")
            {
                MessageBox.Show("chengggo");
            }

        }

        /// <summary>
        /// 添加一个新的文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_Addfolder(object sender, ExecutedRoutedEventArgs e)
        {
            
            //拿到要添加文件夹的父文件夹节点
            string sourceParentId = ((e.OriginalSource as TextBlock).DataContext as Item).Id;
            //拿到用户的配置参数
            string UserId = ConfigService.GetSettingString("UserId");
           
                //输入要新建的文件夹的名称
            new InputBox(this).ShowDialog();
            string sourceName = viewModel.NewFileName;
            string url_newFile = $"/api/file/folder/{UserId}/{sourceName}/{sourceParentId}";
            var respone_newFile = await httpClient.GetAsync(url_newFile);
            respone_newFile.EnsureSuccessStatusCode();
            var product_newFile = await respone_newFile.Content.ReadFromJsonAsync<ApiResult<SourceDto>>();
            //首先处理错误信息
            //判断服务器传回的当前用户是否有权限
            if (product_newFile.Errors != null)  //如果传回来的数据当中存在错误，就进行以下的操作
            {
                if (product_newFile.Errors.ToString().Contains("[800]"))
                {
                    MessageBox.Show("您没有权限添加！");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[1000]"))
                {
                    MessageBox.Show("选中的文件夹不存在");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[900]"))
                {
                    MessageBox.Show("添加操作失败");
                    return;
                }
            }
            //拿到相关的数据
            SourceDto sourceDto = product_newFile.Data;
            var item = new Item { Id = sourceDto.StrGuid, ParentID = sourceDto.ParentId, DisplayText = sourceDto.SourceName };
            //将单个项目添加到列表中
            folderFileTree.Add(item);
            //再次更新上下文,三个语句套件
            viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
            viewModel.CreateItemTree();
            this.treeView1.ItemsSource = viewModel.FileItems;

        }

        /// <summary>
        /// 添加文件的引用，添加相应的文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_Addfile(object sender, ExecutedRoutedEventArgs e)
        {
            //拿到要添加文件夹的父文件夹节点
            Item currentItem = (e.OriginalSource as TextBlock).DataContext as Item;
            string sourceId = currentItem.Id;
            //拿到用户的配置参数
            string UserId = ConfigService.GetSettingString("UserId");

            //输入要新建的文件夹的名称
            new InputBox(this).ShowDialog();
            string fileName = viewModel.NewFileName;

            string url_newFile = $"/api/file/file/{UserId}/{fileName}/{sourceId}";  //这里面的sourceId就是GUID类型的，可以直接使用
            var respone_newFile = await httpClient.GetAsync(url_newFile);
            respone_newFile.EnsureSuccessStatusCode();
            var product_newFile = await respone_newFile.Content.ReadFromJsonAsync<ApiResult<DocumentDto>>();
            //首先处理错误信息
            //判断服务器传回的当前用户是否有权限
            if (product_newFile.Errors != null)
            {
                if (product_newFile.Errors.ToString().Contains("[800]"))
                {
                    MessageBox.Show("您没有权限添加！");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[1000]"))
                {
                    MessageBox.Show("选中的文件夹不存在");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[900]"))
                {
                    MessageBox.Show("添加失败");
                    return;
                }
            }
            //执行到该步骤 说明添加文件的请求已经得到了认可，开始在本地进行文件的创建及文件的上传
            //首先判断是否存在文件夹,若不存在文件夹则进行文件夹的创建工作
            if (!Directory.Exists(System.IO.Path.Combine(ConfigService.localFileFolder, sourceId)))
            {
                Directory.CreateDirectory(System.IO.Path.Combine(ConfigService.localFileFolder, sourceId));
            }
            //开始在该文件夹下创建文件
            string localFilePath = System.IO.Path.Combine(ConfigService.localFileFolder, sourceId, currentItem.DisplayText);
            using (FileStream fileStream = new FileStream(localFilePath, FileMode.Create))
            {
                //任意写入10个字节
                fileStream.Write(new byte[10], 0, 10);
            }
            //对文件进行上传，如果上传成功则进行更改，如果上传失败则进行响应的操作
            UploadFileFunc(localFilePath);

            //拿到相关的数据

            DocumentDto documentDto = product_newFile.Data;
            var item = new Item { Id = documentDto.StrGuid, ParentID = sourceId, DisplayText = documentDto.DocumentName };
            //将单个项目添加到列表中
            folderFileTree.Add(item);
            //再次更新上下文,三个语句套件,[三连套件]
            viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
            viewModel.CreateItemTree();
            this.treeView1.ItemsSource = viewModel.FileItems;

        }

        /// <summary>
        /// 修改文件夹的名称，命令的实现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_Modifyfoldername(object sender, ExecutedRoutedEventArgs e)
        {
            //拿到要添加文件夹的父文件夹节点,GUID
            string sourceId = ((e.OriginalSource as TextBlock).DataContext as Item).Id;
            //拿到用户的配置参数
            string UserId = ConfigService.GetSettingString("UserId");
            //输入要修改文件夹的名称
            new InputBox(this).ShowDialog();
            string sourceName = viewModel.NewFileName;
            string url_newFile = $"/api/file/modify-folder-name/{UserId}/{sourceId}/{sourceName}";
            var respone_newFile = await httpClient.GetAsync(url_newFile);
            respone_newFile.EnsureSuccessStatusCode();
            var product_newFile = await respone_newFile.Content.ReadFromJsonAsync<ApiResult<bool>>();
            //首先处理错误信息
            //判断服务器传回的当前用户是否有权限
            if (product_newFile.Errors != null)
            {
                if (product_newFile.Errors.ToString().Contains("[800]"))
                {
                    MessageBox.Show("您没有权限添加！");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[1000]"))
                {
                    MessageBox.Show("选中的文件夹不存在");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[900]"))
                {
                    MessageBox.Show("添加失败");
                    return;
                }
            }

            //拿到相关的数据

            bool Result = product_newFile.Data;
            if (Result)
            {
                //修改文件夹的名称
                foreach(Item item in folderFileTree)
                {
                    if(item.Id == sourceId)
                    {
                        item.DisplayText = sourceName;
                        break;
                    }
                }
                //再次更新上下文,三个语句套件,[三连套件]
                viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
                viewModel.CreateItemTree();
                this.treeView1.ItemsSource = viewModel.FileItems;
            }

        }

        /// <summary>
        /// 修改一个文件的名字，向文件服务器请求修改文件名称，与修改文件夹是相对的
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_Modifyfilename(object sender, ExecutedRoutedEventArgs e)
        {
            //拿到要修改文件的文件GUID
            string docuId = ((e.OriginalSource as TextBlock).DataContext as Item).Id;
            //拿到用户的配置参数
            string UserId = ConfigService.GetSettingString("UserId");
            //输入要修改文档的名称
            new InputBox(this).ShowDialog();
            string docuName = viewModel.NewFileName;
            string url_newFile = $"/api/file/modify-file-name/{UserId}/{docuId}/{docuName}";
            var respone_newFile = await httpClient.GetAsync(url_newFile);
            respone_newFile.EnsureSuccessStatusCode();
            var product_newFile = await respone_newFile.Content.ReadFromJsonAsync<ApiResult<bool>>();
            //首先处理错误信息
            //判断服务器传回的当前用户是否有权限
            if (product_newFile.Errors != null)
            {
                if (product_newFile.Errors.ToString().Contains("[800]"))
                {
                    MessageBox.Show("您没有权限添加！");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[1000]"))
                {
                    MessageBox.Show("选中的文件夹不存在");
                    return;
                }
                if (product_newFile.Errors.ToString().Contains("[900]"))
                {
                    MessageBox.Show("添加失败");
                    return;
                }
            }

            //拿到相关的数据

            bool Result = product_newFile.Data;
            if (Result)
            {
                //修改文件夹的名称
                foreach (Item item in folderFileTree)
                {
                    if (item.Id == docuId)
                    {
                        item.DisplayText = docuName;
                        break;
                    }
                }
                //再次更新上下文,三个语句套件,[三连套件]
                viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
                viewModel.CreateItemTree();
                this.treeView1.ItemsSource = viewModel.FileItems;
            }

        }

        /// <summary>
        /// 请求网络并判断当前用户有没有对某一个资源（文件夹或文件等）的管理应用权限
        /// </summary>
        /// <param name="sourcePath"></param>
        /// <returns></returns>
        private async Task<string> CheckSourceAuth(string sourcePath)
        {
            //对路径进行编码
            sourcePath = PasswordGenerate.PathEncode(sourcePath);

            //拿到用户的配置参数
            string UserId = ConfigService.GetSettingString("UserId");

            string url = $"/api/file/check-user-source-auth/{UserId}/{sourcePath}";
            var respone = await httpClient.GetAsync($"/api/file/check-user-source-auth/{UserId}/{sourcePath}");
            respone.EnsureSuccessStatusCode();
            var product = await respone.Content.ReadFromJsonAsync<ApiResult<string>>();
            string authResult = product.Data;
            return await Task.FromResult(authResult);
        } 
        /// <summary>
        /// 用户测试 检查资源的完整性
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void CheckSource(object sender, RoutedEventArgs e)
        {
            try
            {
                var values = new List<KeyValuePair<string, string>>();
                values.Add(new KeyValuePair<string, string>("username", "1"));
                var content = new StringContent("sss");
                var respone = await httpClient.GetAsync("/api/file/request-file-dir/sss");
                respone.EnsureSuccessStatusCode();
                var product = await respone.Content.ReadFromJsonAsync<ApiResult<List<SourceDto>>>();

                List<SourceDto> sourceDtos = product.Data;

                viewModel.StudentLists = new ObservableCollection<SourceDto>(sourceDtos);

                //ConsoleClientLogger consoleClientLogger = new ConsoleClientLogger(new ClientErrorNotifier(new AntDesign.MessageService()), new Logger<ConsoleClientLogger>(new LoggerFactory()));
                //ApiCaller apiCaller = new ApiCaller(httpClient, consoleClientLogger);
                //SourceService sourceService = new SourceService(apiCaller);
                //try
                //{
                //    var sss = sourceService.GetPage(1, 10).Result;
                //}
                //catch (Exception we)
                //{

                //    MessageBox.Show(we.Message);
                //}

            }
            catch (Newtonsoft.Json.JsonException jex)
            {
                MessageBox.Show(jex.ToString());
            }
            catch (HttpRequestException ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {

            }

        }

        /// <summary>
        /// 用于拉取参数化信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_FetchParaData(object sender, RoutedEventArgs e)
        {
            string dataType = "洞口";
            int MajorId = 1;
            string url = $"/api/file/pull-json-data/{dataType}/{MajorId}";
            var respone = await httpClient.GetAsync(url);
            respone.EnsureSuccessStatusCode();
            var product = await respone.Content.ReadFromJsonAsync<ApiResult<List<ParametricDataDto>>>();
            viewModel.ParametricDataDtos = new ObservableCollection<ParametricDataDto>(product.Data);

            //显示相关的参数化文件
            ParaDataWin paraDataWin = new ParaDataWin(this);
            paraDataWin.ShowDialog();
        }


        /// <summary>
        /// 对某一个特定的文件（用户所拥有的文件，权限为1）进行同步,对文件进行同步
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Command_SychonizeAFile(object sender, ExecutedRoutedEventArgs e)
        {
            //拿到配置文件的目录
            string ConfigPath_Docu = System.IO.Path.GetTempPath() + @"CRDCCollaboPlatConfig\Revit\DocumentInfo.CRDC";
            
            //首先检测文件夹的权限
            //拿到ROOt路径的字符串长度
            int temp = ConfigurationManager.AppSettings["RootPath"].Length;
            //对路径进行裁剪，达到上传服务器的要求
            string source = (e.OriginalSource as DataGrid).CurrentItem.ToString().Substring(temp);
            DocumentDto fileToSychonize = new DocumentDto();
            fileToSychonize.DocumentPath = PasswordGenerate.PathEncode(source);
            //尝试在本地配置文件中查找该文件是否已经与服务器同步，若已经与服务器进行了同步，则需要拿到这个文件的GUID 
            Dictionary<string, string> keyValuePairs = ConfigService.DictFromFile(ConfigPath_Docu);
            foreach(var item in keyValuePairs)
            {
                if(item.Value == source)
                {
                    fileToSychonize.StrGuid = item.Key;
                    break;
                }
            }
            //拿到用户的ID值
            string UserId = ConfigService.GetSettingString("UserId");

            //对文件进行网络请求
            //拿到服务器端发回的关于运行结果的DocumentDto文件
            var response = await httpClient.PostAsJsonAsync<DocumentDto>($"/api/file/sychonize-a-file/{UserId}",fileToSychonize);
            response.EnsureSuccessStatusCode();
            var products = await response.Content.ReadFromJsonAsync<ApiResult<DocumentDto>>();
            //拿到GUID的结果值，若为0000 或 1111 则表明已经在服务器端对名称进行了更新和修改，若为真是GUID表示服务器新建文件成功，若为eeee则出现错误，进行回滚
            string strGuid = products.Data.StrGuid;
            if(strGuid == "eeee" || strGuid == null)//若服务器端已经发生了错误
            {
                MessageBox.Show("服务端发生错误！");
            }else if (strGuid == "0000"||strGuid == "1111")  //服务端更新了文件信息
            {
                MessageBox.Show("更新完成");
            }
            else //拿到服务器端认证过的GUID后，将GUID值保存到TXT数据库中
            {
                Dictionary<string, string> kpv_localFiles = ConfigService.DictFromFile(ConfigPath_Docu);
                kpv_localFiles.Add(strGuid, PasswordGenerate.PathDecode(products.Data.DocumentPath));
                ConfigService.DictToFile(kpv_localFiles, ConfigPath_Docu);
            }

        }


        private async void GetFileItemsFromSerExcute(object sender,  RoutedEventArgs e )
        {
            
                //内存状态下的目录树,初始化
            folderFileTree = new List<Item>();

            MessageBox.Show("sss");
            //首先请求文件夹信息
            string username = "admin";
            string url_folder = $"/api/file/request-file-dir/{username}";
            var respone_folder = await httpClient.GetAsync(url_folder);
            respone_folder.EnsureSuccessStatusCode();
            var product_folder = await respone_folder.Content.ReadFromJsonAsync<ApiResult<List<SourceDto>>>();
            List<SourceDto> sourceDtos = product_folder.Data;
            foreach (SourceDto sourceDto in sourceDtos)
            {
                //声明单个项目
                var item = new Item { Id = sourceDto.StrGuid, ParentID = sourceDto.ParentId, DisplayText = sourceDto.SourceName };
                //将单个项目添加到列表中
                folderFileTree.Add(item);

            }
            // 更新上下文,三个语句套件
            viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
            viewModel.CreateItemTree();
            this.treeView1.ItemsSource = viewModel.FileItems;

            //其次在更新文件 
            string url_file = $"/api/file/request-documents/{username}";
            var respone_file = await httpClient.GetAsync(url_file);
            respone_file.EnsureSuccessStatusCode();
            var product_file = await respone_file.Content.ReadFromJsonAsync<ApiResult<List<DocumentDto>>>();
            List<DocumentDto> documentDtos = product_file.Data;
            foreach(DocumentDto documentDto in documentDtos)
            {
                var item = new Item { Id = documentDto.StrGuid, ParentID = documentDto.ParentId, DisplayText = documentDto.DocumentName };
                folderFileTree.Add(item);
            }
            //再次更新上下文,三个语句套件
            viewModel.FileItemsData = TreeHelper.DeepCopyByBin<IList<Item>>(folderFileTree);
            viewModel.CreateItemTree();
            this.treeView1.ItemsSource = viewModel.FileItems;

        }


    }
}
